Skip to content

Fix TypeError when JSON login password is a non-string value - #1256

Closed
miettal wants to merge 1 commit into
pallets-eco:mainfrom
miettal:fix/login-non-string-password-typeerror
Closed

Fix TypeError when JSON login password is a non-string value#1256
miettal wants to merge 1 commit into
pallets-eco:mainfrom
miettal:fix/login-non-string-password-typeerror

Conversation

@miettal

@miettal miettal commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

LoginForm.validate() only checks if password.data is truthy, not its type. Flask-WTF supports JSON request bodies, so a login POST with a non-string password (e.g. a dict) passes this check.

That value then reaches hash_password() / get_hmac() or password_util.normalize() unchanged, and both crash with an unhandled TypeError instead of a normal validation error.

Fix

Add an isinstance(self.password.data, str) check in LoginForm.validate(), right after the existing password-required assertion. Non-string passwords are now rejected like any other invalid login.

Testing

  • Added test_non_string_json_password_auth in tests/test_basic.py.
  • Confirmed it reproduces the crash on main (reverted the fix locally) and passes with the fix.
  • Ran the full test_basic.py suite locally: no new failures (a few pre-existing skips for optional deps I don't have installed: pymongo, peewee, asgiref, flask_sqlalchemy_lite).
  • flake8 and black --check are clean.

Found via a Sentry error recurring across several apps that all use Flask-Security-Too's default JSON login, so this likely affects any app accepting JSON logins.

LoginForm.validate() only checks password.data truthiness via
DataRequired()/InputRequired(), not its type. A JSON login body can
set password to a dict/list/number/bool instead of a string, which
then crashes hash_password()/get_hmac() or password_util.normalize()
with an unhandled TypeError instead of failing validation cleanly.

Add an isinstance check right after the existing password-required
assertion so non-string passwords are rejected like any other invalid
login.
@jwag956

jwag956 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

thanks for pointing this out. wow. This is a bigger issue than password - and I think the solution should involve all the StringField() inputs - possibly with a custom validator.
Unless you really want to tackle that - I am happy to convert this to a bug report and work on the general solution.

@miettal

miettal commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for the quick response.
If the project prefers a common/root solution (like StringField() inputs improvement), I'd be happy to give it a try.

@jwag956

jwag956 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Ok - always looking for contributors - this will be a fairly extensive change and I would want to get this into the upcoming 5.9 release (hopefully in the next month). As part of pallets-eco we strive for human collaborators and will quickly close out obvious AI generated PRs.

I think the right approach is to create a validator in forms.py:

`class IsString(ValidatorMixin):
def init_(self, *args, **kwargs):
if "message" not in kwargs:
kwargs["message"] = "API_ERROR"
super().init(*args, **kwargs)

def call:
if not isinstance(field.data, str):
raise StopValidation(self.message) # something like this to get the default message)
super().call(form, field)

`

Then add this to most/all of the form StringField. Note that there are a few files that define forms that also have StringField. Would also want to add the validator to EmailFields....

Testing would include at least one test that the message is getting properly localized.

Whew!

Let me know if you are up for tackling this...
Thanks.

@miettal

miettal commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

OK!, I'll write code by hand mainly and Use AI is limited to assistance.
My job coding almost AI now, So hand coding is after long time. I'm very happy to requiring Human Inteligence.

jwag956 added a commit that referenced this pull request Jul 28, 2026
…values from JSON requests (#1258)

Replace #1256 with a
root-cause fix.

 - add IsString() validator.
 - add IsStringOrInt() validator.
 - add IsString/IsStringOrInt validation for each string-required field.
 - add a test case confirming translation works.
 - add a test case confirming the new validators work.
 - add special handling for ConfirmRegisterForm/RegisterFormV2.
- add a test case for special handling for
ConfirmRegisterForm/RegisterFormV2.
@miettal

miettal commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Another solution was merged, This this PR is close.
#1258

@miettal miettal closed this Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants